package com.example.authorization_server.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import static com.example.common.constant.Constant.*;


/**
 * @author 罗俊华
 * @date 2021/10/9 - 11:19 上午
 */
@Slf4j
@Order(SecurityProperties.BASIC_AUTH_ORDER - 10)
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    /**
     * 创建认证管理器
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 新增了一条spring security 的过滤器链，并且其优先于 fallback 过滤器链执行
     * fallback 的过滤器链的优先级为 @Order(SecurityProperties.BASIC_AUTH_ORDER)
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 这里定义的拦截顺序非常重要
        http.authorizeRequests()
                /**
                 * 注意：这里如果不指定的话，会把 /oauth/ 的请求都给拦截下来，造成无法访问任何资源
                 *
                 */
                .antMatchers(
                        "/oauth/**",
                        LOGIN_PAGE,  // 跳转登陆页面的controller路径
                        LOGIN_PROCESSING_URL // 进行登陆的请求路径
                )
                    .permitAll()
                .antMatchers("/**")
                .authenticated()

                .and()
                .logout()
                .logoutUrl(LOGOUT_URL)
                .logoutSuccessUrl(LOGIN_PAGE)  //退出登陆成功之后，跳转到登陆页面

                .and()

                /**
                 * 注意： 登陆相关的信息还是需要进行配置的，
                 * 因为当 client 请求 authorize 服务器 授权的时候需要进行登陆
                 * 登陆成功了之后才能决定是否进行授权
                 */
                .formLogin()

                //声明了我们提供的自定义登录页面的路径
                //当SpringSecurity断定用户没有认证并且需要登录的时候，它就会将用户重定向到该路径
                .loginPage(LOGIN_PAGE) // 必须以 '/' 开头，然后此路径要对应一个 controller

                // 设置用户点击登陆时，验证用户名和密码的url地址
                // 注意：html 中的form表单也必须是这个地址
                // 在 loginController 中使用了 ModelAndView 将此常量传递给了 thymeleaf 模版引擎
                .loginProcessingUrl(LOGIN_PROCESSING_URL)
                .defaultSuccessUrl(HELLO)   // 默认登陆成功之后跳转的地址
                .usernameParameter("username")
                .passwordParameter("password")




        ;

    }
}
